﻿
using KnBinarySerializer.Field;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace KnBinarySerializer
{
    internal class ClassFormatterV2 : IFormatter
    {        
        public Type GetHandleType()
        {
            return typeof(object);
        }

        public byte GetKey()
        {
            return (byte)0;
        }
        public bool IsFixLen()
        {
            return false;
        }
       
        public int WriteBytes(BianaySerializeManager stream, object obj)
        {
            int len = 0;
            if (obj != null)
            {
                Type type = obj.GetType();
                ClassSerial serial;//通过该序列取回属性的次序
                Dictionary<string, IClassField> fields;
                len += stream.WriteClassSerial(type,out serial,out fields);//写入类的序列                
                foreach (var one in serial.Fields)
                {
                    IClassField property = fields[one.Value];
                    object objVal = property.GetValue(obj, null);
                    if (objVal == null)
                        len += stream.WriteNull();
                    else
                        len += stream.SerializeObject(objVal);//按次序写入各属性的值
                }
            }
            return len;
        }

        public object ReadBytes(BianaySerializeManager content, int maxLen, Type type)
        {
            if (maxLen == 0)
                return null;
            long start = content.GetPosition();
            object obj = ClassSerialContext.CreateObject(type);
            int index = -1;
            Dictionary<string, IClassField> fields = ClassSerialContext.GetFields(type);
            var serial = content.ReadClassSerial();
            while (content.GetPosition() - start < maxLen)
            {
                index++;
                string name = serial.Fields[index];
                if (!fields.ContainsKey(name))
                {
                    byte misKey = content.ReadByte();
                    IFormatter formatter = content.GetFormatter(misKey);
                    int misLen = 0;
                    if (formatter.IsFixLen())
                    {                        
                        misLen = content.GetBytesLen(formatter.GetHandleType());
                        if (misLen == -1)
                            throw new Exception($"固定长度属性无法忽略，请定义{type.Name}.{name}[{formatter.GetHandleType().Name}]属性");
                    }
                    else
                    {
                        misLen = content.ReadInt();
                    }
                    content.Skip(misLen);
                    continue;
                }
                IClassField property = fields[name];
                if (property.CanWrite)
                {
                    object objVal = content.DeSerializeObject(property.PropertyType);
                    property.SetValue(obj, objVal, null);
                }
                else
                {
                    //不能写的，视为子进行子项添加
                    object objVal = property.GetValue(obj, null);
                    if (objVal == null)
                        throw new Exception("不能写的属性，需要类自行初始化才能进行反序列化");
                    content.DeSerializeToObject(objVal);
                }
            }
            return obj;
        }
    }

    
}
